On this page

Skip to content

ASP.NET Core Web API Introduction - A Brief Discussion on non-RESTful Route Overriding

TLDR

  • By inheriting from BasicController and setting [Route("[controller]/[action]")], you can centrally manage API routes in a non-RESTful architecture.
  • To override the Controller-level route, simply use the [Route] attribute directly on the Controller.
  • If an Action needs to completely ignore the Controller-level route configuration, prefix the Action's [Route] with / or ~.
  • Avoid using [Route] on both the Controller and the Action simultaneously, as this leads to route concatenation, resulting in unexpected URLs.
  • If you only need to modify the URL name of an Action, it is recommended to use the [ActionName] attribute instead of [Route].

Unified Route Management and Basic Configuration

In a non-RESTful style Web API, to avoid redundant route definitions, you can create an abstract BasicController to unify route rules.

When you might encounter this: When the project uses a Controller/Action format and you want to reduce the maintenance cost of repeatedly writing route attributes for every Controller.

csharp
[ApiController]
[Route("[controller]/[action]")]
public abstract class BasicController : ControllerBase {
}

public class TestRouteController : BasicController {
    // URL: /TestRoute/TestAction
    [HttpPost]
    public void TestAction() {
    }
}

Route Overriding and Path Concatenation Issues

When the existing API architecture needs adjustment, or individual Actions require specific paths, it is essential to understand the behavioral differences of the [Route] attribute at different levels.

When you might encounter this: When you need to customize paths for a specific Controller or Action without affecting global settings, or when you accidentally trigger the default route concatenation behavior.

Route Behavior Analysis

  • Controller-level override: Using [Route] on a Controller will directly replace the settings from BasicController.
  • Action-level concatenation: If both the Controller and the Action define [Route], ASP.NET Core will concatenate the two paths.
  • Forced override (ignoring prefix): Adding / or ~ to the prefix of an Action's [Route] forces it to ignore the Controller-level route configuration.
csharp
[Route("Override/[action]")]
public class TestRouteController : BasicController {
    // Scenario: Controller overrides Route, Action does not handle it
    // URL: /Override/OverrideController
    [HttpPost]
    public void OverrideController() {
    }

    // Common misuse: Both Controller and Action override, leading to path concatenation
    // URL: /Override/OverrideAction/Action/OverrideAction
    [HttpPost]
    [Route("Action/[action]")]
    public void OverrideAction() {
    }

    // Scenario: Action forces ignoring Controller settings using "/"
    // URL: /Action/OnlyAction
    [HttpPost]
    [Route("/Action/[action]")]
    public void OnlyAction() {
    }

    // Scenario: Action forces ignoring Controller settings using "~"
    // URL: /Action/OnlyAction2
    [HttpPost]
    [Route("~/Action/[action]")]
    public void OnlyAction2() {
    }

    // Scenario: Simply modifying the Action name without affecting the route structure
    // URL: /Override/Rename
    [HttpPost]
    [ActionName("Rename")]
    public void RenameAction() {
    }
}

Conclusion and Recommendations

  • To unify API naming styles, prioritize using BasicController for global route definitions.
  • If you need to adjust the path for a specific Action, consider using the [ActionName] attribute first, as this avoids the complexity introduced by route concatenation.
  • If you must use [Route] to override an Action path, be sure to add the / or ~ prefix to ensure the path meets expectations and to avoid generating overly long, nested URLs.

Changelog

  • 2024-04-16 Initial version created.